#define D2D_INPUT_COUNT 1
#define D2D_INPUT1_SAMPLE

#include "d2d1effecthelps.hlsli"

float2 size;

float4 displacment(float p){
    p.x/=size.x/size.y;
    float3 tex = D2DSampleInput(p.xz/9.,).rgb;
    tex = clamp(tex,float3(0),float3(1));
    return float4(length(tex),tex);
}

float  obox(in float3 p,in float3 b){
    return length(max(abs(p)-b),0));
}

float map (in float3 p){

    float scal =1;
    float box =0;

    float x = 8;
    float z = x*size.y/size.x;

    float4 disp = displacment(p+float3(x,1,z));

    float y = disp.x*scale;
    if(p.y>0)
        box = obox(p,float4(x,y,z));
        else
        box = obox(p,float3(x,1,z));

    return vec4(box,disp.yzw);
}

float softshadow(in float3 ro,in float3 rd,in float mint,in float tmax)
{
    float res = 1;
    float t = mint;
    for(int i =0;i<16;i++){
        float h = map (ro+rd*t).x;
        res = min (res,8*h/t);
        t += clamp(h,0.02,0.10);

    }
    return clamp (res,0,1);
}


float3 calcNormal(in float3 pos){
    float3 eps = float3( 0.05, 0.0, 0.0 );
	float3 nor = float3(
	    map(pos+eps.xyy).x - map(pos-eps.xyy).x,
	    map(pos+eps.yxy).x - map(pos-eps.yxy).x,
	    map(pos+eps.yyx).x - map(pos-eps.yyx).x );
	return normalize(nor);
}

float calcAO( in float3 pos, in float3 nor )
{
	float occ = 0.0;
    float sca = 1.0;
    for( int i=0; i<5; i++ )
    {
        float hr = 0.01 + 0.12*float(i)/4.0;
        float3 aopos =  nor * hr + pos;
        float dd = map( aopos ).x;
        occ += -(dd-hr)*sca;
        sca *= 0.95;
    }
    return clamp( 1.0 - 3.0*occ, 0.0, 1.0 );    
}

// ray marching
float march(float3 ro, float3 rd, float rmPrec, float maxd, float mapPrec)
{
    float s = rmPrec;
    float d = 0.;
    for(int i=0;i<150;i++)
    {      
        if (s<rmPrec||s>maxd) break;
        s = map(ro+rd*d).x*mapPrec;
        d += s;
    }
    return d;
}

float3 OrenNayarLightModel(float3 rd, float3 ld, float3 n){
	float3 col = float3(1.);//cubeMap(uCubeMap, ld, uCubeMapSize.x).rgb;

	float RDdotN = dot(-rd, n);
	float NdotLD = dot(n, ld);
    
    float aRDN = acos(RDdotN);
	float aNLD = acos(NdotLD);
    
	float mu = .3; // roughness
	if (iMouse.z>0.) mu = iMouse.y/iResolution.y;
    
	float A = 1.-.5*mu*mu/(mu*mu+0.57);
    float B = .45*mu*mu/(mu*mu+0.09);

	float alpha = max(aRDN, aNLD);
	float beta = min(aRDN, aNLD);
	
	float albedo = 1.1;
	
	float e0 = 3.1;
	col *= float3(albedo / 3.14159) * cos(aNLD) * (A + ( B * max(0.,cos(aRDN - aNLD)) * sin(alpha) * tan(beta)))*e0;
	
	return col;
}


D2D_SP_ENTRY(main){
    float time = iTime*0.5;
    float cam_a = 3.14159; // angle z
    float cam_e = 6.1; // elevation
    float cam_d = 2.; // distance to origin axis
    float3 camUp=float3(0,1,0);//Change camere up vector here
  	float3 camView=float3(0,0,0); //Change camere view here
  	float li = 0.6; // light intensity
    float prec = 0.00001; // ray marching precision
    float maxd = 50.; // ray marching distance max
    float refl_i = 0.45; // reflexion intensity
    float refr_a = 0.0; // refraction angle
    float refr_i = 0.8; // refraction intensity
    float bii = 0.35; // bright init intensity
    float marchPrecision = 0.3; // ray marching tolerance precision
    
    float2 uv = D2DGetInputCoordinate(0).xy;

    float3 col ;

    float3 ro = float3(-sin(cam_a)*cam_d, cam_e+1., cos(cam_a)*cam_d); //
  	float3 rov = normalize(camView-ro);
    float3 u = normalize(cross(camUp,rov));
  	float3 v = cross(rov,u);
  	float3 rd = normalize(rov + uv.x*u + uv.y*v);
    
    float b = bii;
    
    float d = march(ro, rd, prec, maxd, marchPrecision);
    
    if (d<maxd)
    {
        float2 e = float2(-1., 1.)*0.005; 
    	float3 p = ro+rd*d;
        float3 n = calcNormal(p);//normalize(e.yxx*map(p + e.yxx) + e.xxy*map(p + e.xxy) + e.xyx*map(p + e.xyx) + e.yyy*map(p + e.yyy) );
        //float3 np = normalize(p);
        
        b=li;
        
        float3 reflRay = reflect(rd, n);
        
		float3 refrRay = refract(rd, n, refr_a);

        	float3 refrRay = refract(rd, n, refr_a);
        float3 cubeRefl = D2DSampleInput(0,reflRay).rgb * refl_i;
        float3 cubeRefr = D2DSampleInput(0,reflRay).rgb * refr_i;
        
}